home *** CD-ROM | disk | FTP | other *** search
- Implementation Notes
- on the
- Xgopher client
-
-
- These notes describe Xgopher version 1.3, completed in May 1993.
- The implementor and author of these notes can be contacted at:
-
- Allan Tuchman
- Computing and Communications Services Office (CCSO)
- University of Illinois at Urbana-Champaign
- 1304 W. Springfield Ave.
- Urbana, Illinois 61801
- USA
-
- (217) 244-0048
- a-tuchman@uiuc.edu
-
-
- Source Organization
- -------------------
- The xgopher source files are organized by function. They are:
-
- xgopher.c - main program, initialize X, set up initial request.
- item.c - manage the data fields for gopher items
- itemList.c- create and manage the data structures for gopher items
- dir.c - manage the data fields for gopher directories
- dirList.c - create and manage the data structures for gopher directories
- markList.c- create and manage the bookmark list of gopher items
- util.c - does gopher processing, get and process gopher requests
- misc.c - misc things like time functions that may be host dependent
- net.c - open, read, and write from a network connection
- help.c - manage help file data.
- bkmkfile.c- manage bookmark file load and save
- itemInfo.c- obtain info about a gopher item or directory
- subst.c - perform printf-like substitutions of gopher item data
- jobs.c - keep track of jobs spawned by Xgopher
- sc_*.c - gopher item class processing for each subclass of gopher item
-
- ------ No file above here has any connection to the X window system -----
-
- gui.c - interface between the previous files and X functions
- resources.c- retrieve application resources
- cso.c - create, manage, and process requests for CSO name servers
- index.c - create and manage panel to get keywords for index searches
- panel.c - create and manage the main xgopher panel
- error.c - create and manage the error pop up
- save.c - create and manage the file save pop up and functions
- options.c - create and manage the pop up for changing run-time options
- single.c - create and manage the pop up for entering a special item
- text.c - create and manage the text display pop ups
- version.c - create and manage the version information pop up
- status.c - create and manage the status popup window
- KeyWSink.c- subclass of AsciiSink widget that can highlight
- selected keywords
-
- The include files are used to provide functions definitions,
- configuration options, data structure declarations, share data,
- and define bitmaps. They are:
-
- conf.h - configuration parameters
- gopher.h - data structure definitions for items and directories
- resources.h - the definition of the application resources structure
- appres.h - the global definition of the app. resources structure
- popres.h - subresources for popup window positioning
- typeres.h - subresources for extended type definition
- globals.h - a couple of variables, symbolic constants, and macros
- oneLine.h - text widget translations to enable single line edit mode
- osdep.h - attempt to isolate some OS dependencies for include files.
- MIT_Xosdefs.h- X11R5 OS dependency code from MIT.
- MIT_Xos.h - X11R5 OS dependency header code from MIT.
- version.h - Xgopher version info and display text
- xglobals.h - shared values defined in the X files
- listP.h - resources used only in {mark,dir)List.c (from resources.c)
- panel.h - public header file and macros for panel.c
- compatR4.h - X11R4 compatibility macros
- text.h - data for text.c
- sc_*P.h - private header for each subclass of gopher item
- KeyWSink.h - public header file for KeyWSink widget
- KeyWSinkP.h - private header file for KeyWSink widget
- bitmaps/* - contains bitmaps and icons.
-
- The following are all simple function declaration header files:
- item.h, itemList.c, dir.h, dirList.h, markList.h,
- gui.h, misc.h, net.h, util.h, help.h, cso.h, index.h, error.h,
- bkmkfile.h, itemInfo.h, options.h, single.h, jobs.h, status.h,
- subst.h, sc_*.h
-
-
- Other files:
-
- Imakefile - used to generate a Makefile
- Makefile.NoNo - A LAST RESORT sample Makefile for those without Imake
- README - documentation file - SHOULD READ BEFORE INSTALLATION
- xgopher.help - a sample help file
- xgopher.man - a Unix manual page for xgopher
- Xgopher.ad - the applications defaults file. It MUST be used!
- Xgopher-color.ad - applications color resources file.
- Xgopher-complete.ad - combination of the above two files.
- Xgopher-secure.ad - resources file used for public Xgopher kiosk with
- a touch screen.
- Xgopher-allExtend.ad - Sample app-defaults with lots of extended types.
-
- Files in ./Documents:
- Changes - list of changes since Xgopher 1.2
- Release_Notes - documentation file - describes changes/features of this
- version of Xgopher.
- Edits - notes on string editing for command strings
- Extended-Types - detailed notes on use of extended types, with examples
- Install-Customization -
- Helps the installer customize certain functions
- of Xgopher, including where to find some external
- programs that may be useful.
- Popups - Details on how to use the popup positioning resources
- Porting - Notes on porting Xgopher to other platforms.
- Implementation - documentation file interesting to the programmer
- Sun-names - Some details on problems that Sun's may have in
- resolving host names.
- Sunlib-rebuild - notes on rebuilding a Sun library to help find
- a name server.
- OW3-site.def - a configuration file used for compiling with Sun's
- OpenWindows, release 3.
- OW3-xmkmf.patch- an optional fix to Sun's OpenWindows xmkmf program.
-
-
- I have tried to keep major operating system dependencies all in the
- file misc.c and osdep.h. Different versions of Unix may have slightly
- different programming requirements. These slight variations are handled
- through preprocessor directives in the appropriate source files.
-
-
- Resource Usage
- --------------
-
- I have made considerable effort to maintain and reuse every resource
- allocated. Memory for major data structures is never freed back to the
- system, but structures that are no longer in use are maintained and reused
- again later. The idea is that it is expensive to get and build
- things, but cheap to reuse them. This philosophy applies to
- . gopher items (the lines you see on the screen and their selector
- information).
- . gopher directories
- . X window text popups
- . Other popups, panels, and help data.
- . Lists created and used to display the X directory and bookmark
- contents lists.
-
-
- Positioning Popup Windows
- -------------------------
-
- Everyone has there own preferences as to where popups should appear.
- There are good arguments for having them 1) near the cursor, 2) a
- constant position on the main application window, and 3) a constant
- location on the screen.
-
- If you want to change popup positions, here's how to do it in the
- source program. Future versions of Xgopher may allow such
- preferences in the application defaults file.
-
- Text (and help) displays are not transient windows, and I leave their
- placement to the window manager and the user's window manager preferences.
- For all transient windows I place them with a single, pretty general
- function call. The call
-
- positionPopup(w, from, fromWidget, x, y, hJust, vJust);
-
- is used just before poping-up widget w. If one wants to change
- the pop-up location or policy for a specific widget, one need
- only change the parameters to this procedure. The rest or the
- parameters are:
-
- from takes it value from the set of symbolic constants:
- { POS_none, POS_pointer, POS_appPanel, POS_screen }, which
- do respectively, no positioning, position at the pointer
- location, position relative to an application window, or
- position relative to the screen.
-
- fromWidget
- For from=POS_appPanel, this is the widget (window) to position on.
-
- x, y provide a location in percent across the application window
- or screen (depending on from). For example, x=50, y=50
- represents the center of either the window or the screen.
-
- hJust, vJust
- are horizontal and vertical justification requirements. For
- hJust = 0 the left edge of the popup is positioned at x;
- hJust = 1 the center of the popup is positioned at x;
- hJust = 2 the right edge of the popup is positioned at x.
- The same is true for vJust, using top, middle, and bottom
- against y.
-
- These justifications do not take into account the size of
- the window manager decorations, but they're close enough
- anyway to be pretty useful.
-
- After positioning, positionPopup forces the complete popup to lie
- on screen by "shoving" it, if necessary, just enough to get it fully
- on the display.
-
-
- Hacker's Corner
- ---------------
-
- Using the "Enter Gopher Item" menu item and selecting a directory
- but using type=0 (text file), you can capture a raw gopher directory
- response into a text file. I find this useful for debugging and
- for documentation. You can also set type=9 to copy any file in
- binary mode.
-
-
- Differences from Previous Versions of Xgopher
- ---------------------------------------------
-
- The earliest released versions of Xgopher (Xgopher 1.0, 1.1, and 1.1a)
- maintained a notion of a dynamic n-ary tree that the user traversed
- through gopher space. Along with this tree, was the notion of a bookmark
- being a "place", and internal node in this tree. The main gopher data
- structures were maintained by the routines in the file list.c.
-
- For better or worse, the Unix curses client defined peoples expectations
- of bookmark behavior, and indeed, the way gopher space was presented.
- As such, the entire basic data structure has been changed at Xgopher 1.2.
- The n-ary tree has been replaced with a directory stack. Most important,
- bookmarks are no longer places (directories), but things (items). Of
- course, an item may be a directory. The file list.c has been replaced
- with 5 smaller files (item.c, itemList.c, dir.c, dirList.c, markList.c).
-
- Xgopher 1.3 introduced significant changes in the way gopher item
- classes were handled internally, giving far better maintenance control.
- Extended types make source changes unnecessary for adding many new
- gopher types for special purposes, testing, and local customization.
-
-
- Subclass Implementation for Gopher Items
- ----------------------------------------
-
- === This section is totally changed for Xgopher 1.3 ===
-
-
- To implement a sort of subclass using standard C, I introduced
- to the base class a new field, sc, a pointer to a subclass
- structure. For the base class, this points to a structure of
- default (null or unknown) data and methods.
-
- I chose this method instead of one like X uses for widget
- subclassing because 1) I want to be able to reuse items with
- different subtypes without incurring the expense of freeing
- and reallocating them; 2) The subclass records are all of the
- same description; and 3) I don't need to go very deep in
- subclassing.
-
- I also didn't use a function table as would be generated by
- C++, again, because I have a simple, constant subclass record
- structure, and the type (subclass) of an item will not change
- over its useful lifetime.
-
- So, scInfo (struct subClassInfoStruct) contains a few constant
- strings and function references that will be constant for each
- item of that class.
-
-
- Adding a New Internal Item Type to Xgopher
- ------------------------------------------
-
- To add a new class:
-
- 1. create the private class record in a header file named
-
- sc_<type>P.h
-
- It should start out something like this:
-
- /* sc_<type>P.h
- gopher item subclass: <type> */
-
- /* ----- subclass record definition ----- */
-
- scInfo <type>Subclass = {
- "<description of type>",
- prefix<Type>,
- nullHostList,
- checkAccess,
- GI_copyItemToFile,
- copyTypeBinaryEOF,
- GI_noProcess,
- GI<type>Init,
- GI_done,
- GI<type>restart
- };
-
- Also create a public class header with the function definitions.
-
- You can model both of these files on an existing subclass.
-
- 2. Add the prefix<Type> resource by modifying
-
- resources.h
- resources.c
- prefixP.h
- conf.h for the default (PREFIX_<TYPE>)
-
- Follow the examples by looking for "prefixDir" in each file, and do the
- same thing for the new type.
-
- 3. Add the prefix<Type> resource to Xgopher.ad (again, look for the area
- around prefixDir and do the same.
-
- 4. Modify util.c:
- . Add the new header file with all the other "sc_something.h" includes.
- . Add the new type character and subclass record to the list defined by:
-
- static gopherTypeClass types[] = {
- :
- :
- };
-
-
- ===========================================================================
- There now a new type defined in Xgopher, but with only default behavior.
- It can only be accessed by a "copy", not a "fetch". Copy will be in
- binary (not ascii). The only access limits imposed my be against ftp
- (no host access lists). And there is not special processing upon a
- restart command.
-
- Time to customize this item. If it is very similar in behavior to another
- gopher type, it is a good idea to look at the subclass methods for that
- other type (in the sc_other.[hc] files before proceding.
- ===========================================================================
-
- 5. For each of the following routines, write new versions if the
- default behavior is not acceptable.
- . The procedures should be placed in the file sc_<type>.c
- . The procedures should be declared static unless they are
- callbacks or some other unusual circumstance dictates.
- . Function declaration headers for these procedures should be
- included in sc_<type>.h before the subclass record is defined.
- . The names below are suggested names.
-
- A. checkAccess - suggested name is GI<Type>_checkAccess
- Any checks to limit access to an item by host, domain, ftp,
- or other criteria. The default procedure often suffices.
-
- B. copyItemToFile - suggested name is GI<Type>_copyItem
- Copy processing procedure for this item type when the "copy
- selection to file" button is pressed. The default procedures
- GI_copyItemToFile or GI_noCopyItem often suffice.
-
- C. process - suggested name is GI<Type>_process
- The normal processing procedure for this item type when the
- "fetch selection" button is pressed. Either GI_noProcess is
- useful or a custom procedure is written for this method.
- Process procedures are responsible for keeping the user
- informed about what's going on - the current status of
- their request. Although not necessary for correct function,
- it is nice to provide some feedback. The status popup
- shared by other classes may be used.
-
- D. copy - suggested name is copyBin, copyAscii, or
- GI<Type>_copy
- Normally, one of the two existing procedures copyBin or copyAscii
- is used.
-
- E. restart - suggested name is GI<Type>_restart
- This is a class-level restart. It is used for example, to pop
- down any windows associated with a CSO name server, an index
- search query, or text windows.
-
-
- Gopher Directory Data Structure
- -------------------------------
-
- === This section is totally changed as of Xgopher 1.2 ===
-
- The gopher directories are maintained in a stack. The stack is
- implemented as modified last-in-first-out (LIFO) data structure.
- The modification is that a "pop" operation decrements the top-of-stack
- pointer as usual, but the previous top-of-stack item is not yet freed
- or removed from the stack. This occurs when the next "push" operation
- occurs. This allows the stack to be traversed backward, then forward
- again (even though the forward traversal is not normal stack behavior).
- Strange? Perhaps; but it doesn't cost anything to do it this way, and
- it allows one to recover easily from a mistaken "go-back" type of command.
- It is also cheaper for the user, since the contents of the directories
- are maintained (not refetched) as long as they are maintained in the
- stack.
-
- The stack, then, may look like this:
-
- firstDir currentDir--+
- | |
- | V
- | +-----+------+ +-----+------+ +-----+------+ +-----+------+
- +->| dir | next+|--> ... -->| dir | next+|-->| dir | next+|-->| dir | NULL |
- | 1 | | | N-2 | | | N-1 | | | N | |
- +-----+------+ +-----+------+ +-----+------+ +-----+------+
-
- currentDir normally would point as the last directory in the list.
- In the diagram above, the user has selected the "previous directory"
- function to return one level back.
-
- If the user now selects anything except "move forward" (NOT A FUNCTION
- DEFINED BY DEFAULT), then this new selection will replace directory N
- and all of its successors. Each directory from N on is released.
-
- Once a directory is released, the directory data structure
- is removed from the stack and moved back to a "free list".
-
- Gopher items are saved (cached) with the directory until either the
- directory is released or they become stale. A time field in the directory
- structure identifies the time that the directory contents were
- last fetched. Whenever the contents are needed, the time is
- checked, and if some user-specified threshold of elapsed time
- is exceeded, then the directory contents are freed and re-requested
- from the server.
-
-
- Directory Node structure (gopherDir)
-
- gopherItem
- .
- / \
- |
- |
- +----------+--------------+------+
- gopherDir <--|+previous | selectorItem | next+|----> gopherDir
- +----------+--------------+------+
- | created | contents |
- +----------+---------------------+
- |
- |
- \ /
- .
- gopherItemList
-
-
- A gopherItemList is simply a first/last pointer structure:
-
- +--------+
- | first +|---> gopherItem
- +--------+
- | last +|---> gopherItem
- +--------+
-
- And the gopherItem structure is:
-
- +------+------+------+------+
- | type | name | path | next+|--->
- +------+------+------+------+
- | host | port | plus |
- +------+------+-------------+
-
-
- Button Sensitivity
- ------------------
-
- The buttons are set sensitive according to the following conditions
-
- . Fetch: if ANYTHING selected
- . Copy: if ANYTHING selected
- . Previous: if previousDir != NULL
- . RemoveMark: if ANY MARK selected
- . RemoveAllMarks: if markListLen != 0
- . LoadMarks: if BookmarkFile != NULL and != empty string
- . SaveMarks: if BookmarkFile != NULL and != empty string and
- allowBookmarkSave and markListLen != 0
- . Info: if ANYTHING selected ==> label = "info on item"
- else if currentDir exists ==> label = "info on directory"
- . Mark: if ANY NON-MARK selected ==> label = "mark item"
- else if currentDir exists ==> label = "mark directory"
-
-
- Widget Tree
- -----------
-
- If you want to better customize some of the widgets or perhaps modify
- Xgopher, a widget tree is helpful. This one isn't beautiful, but
- it was up to date as of the release of Xgopher 1.3.
- Each line contains first the widget class, then the instance name.
- Indentation shows the parent-child relationships.
-
- Xgopher xgopher
- Paned gopherPanel
- Form statusForm
- Command quit
- MenuButton other
- SimpleMenu otherActionsMenu
- SmeBSB copy
- SmeBSB unmarkAll
- SmeBSB loadMarks
- SmeBSB saveMarks
- SmeBSB options
- SmeBSB oneItem
- SmeBSB version
- SmeBSB restart
- Command help
- Label status
- Form directoryForm
- Label directoryTitle
- Viewport directoryView
- Core clip
- Scrollbar vertical
- List directory
- Box goBox
- Command fetch
- Command info
- Command up
- Simple spacer
- Command mark
- Command unmark
- Form bookmarkForm
- Label bookmarkTitle
- Viewport bookmarkView
- Core clip
- Scrollbar vertical
- List bookmark
- Grip grip
- Grip grip
- TransientShell errorDialogShell
- Dialog errorDialog
- Label icon
- Label label
- Command ok
- TransientShell optionsPanel
- Form optionsForm
- Box buttonBox
- Command done
- Command cancel
- Command help
- Form itemsForm
- Box showWhatBox
- Toggle showWhat
- Label showWhatLabel
- Box appendBkBox
- Toggle appendBk
- Label appendBkLabel
- Box loadBkBox
- Toggle loadBk
- Label loadBkLabel
- Box resetBox
- Toggle reset
- Label resetLabel
- Form bkSaveForm
- Label bkSaveLabel
- Text bkSave
- Form printCmdForm
- Label printCmdLabel
- Text printCmd
- Form imageCmdForm
- Label imageCmdLabel
- Text imageCmd
- Form telCmdForm
- Label telCmdLabel
- Text telCmd
- Form t3270CmdForm
- Label t3270CmdLabel
- Text t3270Cmd
- TransientShell singlePanel
- Form singleForm
- Box buttonBox
- Command done
- Command cancel
- Command clear
- Command mark
- Command help
- Form itemsForm
- Form giTypeForm
- Label giTypeLabel
- Text giType
- Form giNameForm
- Label giNameLabel
- Text giName
- Form giPathForm
- Label giPathLabel
- Text giPath
- Form giHostForm
- Label giHostLabel
- Text giHost
- Form giPortForm
- Label giPortLabel
- Text giPort
- TransientShell infoDialogShell
- Dialog infoDialog
- Label icon
- Label label
- Command ok
- TopLevelShell csoShell
- Form csoForm
- Label nameServer
- Command csoDone
- SimpleMenu csoFieldsMenu
- SmeBSB Default
- SmeBSB Lookup
- SmeBSB Indexed
- SmeBSB Public
- MenuButton csoFields
- Command csoHelp
- Label csoQueryLabel
- Text csoQueryText
- Command csoDoQuery
- Command csoClearQuery
- Command csoClearText
- Text csoText
- TransientShell indexShell
- Form indexForm
- Command indexDoIndex
- Command indexCancel
- Command indexHelp
- Label indexLabel
- Text indexQueryText
- TransientShell saveShell
- Form saveForm
- Label dirLabel
- Text dirPath
- Label saveLabel1
- Label saveLabel2
- Text fileName
- Label fileErrMessage
- Command ok
- Command cancel
- Command chdir
- Command help
- TransientShell cdShell
- Form cdForm
- Label cdLabel
- Text cdPathName
- Label cdErrMessage
- Command ok
- Command cancel
- Command help
- TransientShell dupFileShell
- Form dupFileForm
- Label label1
- Label labelFile
- Label label2
- Command ok
- Command cancel
- Command append
- Command change
- Command help
-
-
- Special thanks
- ------------------
-
- I want to thank everyone who took the time to send me comments, suggestions,
- and constructive criticism on previous versions of Xgopher.
- Much of the Xgopher 1.3 change was motivated by this feedback.
- Also, thanks to the several people who helped beta test this release.
-
- Of course, the present author assumes responsibility for any
- problems introduced.
-